package cate.game.role.farm.dailyfb;

import cate.common.table.d.*;
import cate.common.table.farm.dailyfb.DailyFbCombatRow;
import cate.common.table.farm.dailyfb.DailyFbTypeRow;
import cate.common.util.GameResult;
import cate.game.play.part.FightSide;
import cate.game.play.proce.play.PlayPO;
import cate.game.res.MixRes;
import cate.game.role.Role;
import cate.game.role.farm.AbstractFarm;
import cate.game.role.farm.dailyfb.msg.DailyFbDataResp;
import cate.game.role.farm.dailyfb.msg.DailyFbOneResp;
import cate.game.role.fight.FuncPosition;
import cate.game.role.fight.Position;
import easy.java.dev.note.NoteClass;
import easy.java.dev.note.NoteField;
import easy.java.practice.errorcode.EcResult;
import org.apache.commons.collections4.CollectionUtils;

import java.util.ArrayList;
import java.util.List;

import static cate.common.table.d.GDFunc.ADVENTURE;

@NoteClass(value = "每日副本")
public class MyDailyFb extends AbstractFarm {
  @NoteField(value = "具体的副本数据")
  public List<DailyFb> fbList;

  public MyDailyFb() {
  }

  @Override
  public void initialize(Role role) {
    super.initialize(role);
    if (fbList == null) {
      fbList = new ArrayList<>();
    }
    if (role.getGame().table.dailyFb == null)
      return;
    List<DailyFbTypeRow> list = role.getGame().table.dailyFb.type.getList();
    for (DailyFbTypeRow row : list) {
      getFb(row.id).initialize(role);
    }
  }

  @Override
  public void onEnter() {
    checkOpen();
    update();
  }


  public DailyFb getFb(int type) {
    DailyFb tar = null;
    for (DailyFb fb : fbList) {
      if (fb.type == type) {
        tar = fb;
      }
    }
    if (tar == null) {
      tar = new DailyFb(type);
      fbList.add(tar);
    }
    return tar;
  }


  public void update() {
    List<Integer> types = role.getGame().table.dailyFb.type.getOpenList();
    for (DailyFb fb : fbList) {
      if (types.contains(fb.type))
        fb.update();
    }
    role.sendNow(new DailyFbDataResp(role));
  }

  @Override
  public void onDaySpan(boolean silence) {
    List<DailyFbTypeRow> list = role.getGame().table.dailyFb.type.getList();
    for (DailyFbTypeRow row : list) {
      getFb(row.id).onDaySpan();
    }

    role.sendNow(new DailyFbDataResp(role));
  }

  @Override
  public int getFuncId() {
    return GDFunc.DAILY_FB;
  }

  @Override
  public void onAfterOpen() {

  }

  @Override
  public int getFightFuncId() {
    return GDFunc.DAILY_FB;
  }

  public EcResult<DailyFb> challenge(int type, int combatNum, boolean mop) {
    EcResult r = new EcResult();
    if (!isOpen()) {
      return r.fail("功能未开启");
    }

    if (fighting) {
      return r.fail("当前战斗未结束");
    }
    DailyFbCombatRow tpl = role.getGame().table.dailyFb.combat.find(type, combatNum);
    if (tpl == null) {
      return r.fail("不存在该关卡");
    }

    DailyFb fb = getFb(type);
    if (fb.playTimes == null)
      fb.initialize(role);
    if (!fb.checkOpen()) {
      return r.fail("该副本未开启");
    }
    if (fb == null) {
      return r.fail("类型异常");
    }
    if (combatNum > fb.combatNumOpen) {
      fb.update();
    }
    if (combatNum > fb.combatNumOpen) {
      String detail = "";
      if (tpl.levelReq > this.role.getBase().level) {
        detail +=
                "\n"
                        + String.format(
                        "等级要求%d,你是%d级",
                        tpl.levelReq,
                        role.getBase().level);
      }
      if (tpl.powerReq > this.role.getBase().powerMax) {
        detail +=
                "\n"
                        + String.format("战力要求%d,你的是%d",
                        tpl.powerReq,
                        role.getBase().powerMax);
      }
      return r.fail(
              String.format(
                      "该副本尚未开启(开启%d,目标%d)%s", fb.combatNumOpen, combatNum, detail));
    }

    if (!mop) {
      // 挑战模式
      // combatNum 只应该等于 combatNumPass+1
      if (combatNum <= fb.combatNumPass) {
        return r.fail("已通过该副本，直接扫荡即可");
      }
      if (combatNum > fb.combatNumPass + 1) {
        return r.fail("请先通过前一个关卡");
      }
    } else {
      // 扫荡模式
      if (combatNum > fb.combatNumPass) {
        return r.fail("尚未通过该副本，请先挑战，然后再扫荡");
      }
      // 扣除钻石
    }
    // 处理 每一关的第一次挑战是免费的 这个逻辑
    boolean firstChallenge = combatNum == fb.combatNumPass + 1;
    //
    if (!firstChallenge) {
      EcResult r_times = getTimes(fb, type, tpl.challengeCostCode);

//            new MixRes(tpl.challengeCostCode)
//            tpl.challengeCost
      if (!r_times.ok()) {
        return r_times;
      }
    }
    //
    if (!mop) {
      // 挑战模式
      EcResult<FightSide> fsr = role.getGame().fight.side.createFightSideByCode(GDFight.Team.B, tpl.instanceId);
      if (fsr.data == null) {
        return r.fail("策划配置的一方阵容不存在 tpl.instanceId=" + tpl.instanceId);
      }
      DailyFbFTC context = new DailyFbFTC(role, tpl);
      context.funcId = getFightFuncId(); // 重置为更细分的每日副本类型
      context.playStory.subType = GDDailyFb.Type.toFuncId(type);
      context.playStory.level = tpl.id;
      context.setPositionApply(ADVENTURE);
      EcResult<PlayPO> fightRes = role.getGame().play.startByRole(role, context, fsr.data);
      if (!fightRes.ok()) {
        return r.fail(fightRes.message);
      }
      this.fighting = true;
    } else {
      // 扫荡模式
      MixRes rewardSwap = new MixRes(tpl.rewardSwapCode);
      rewardSwap.add(role, true, GDOperation.DAILY_FB_MOP_REWARD);
      role.getGame().notice.dialogReward(role, rewardSwap);
    }

    int buyTimeOrigin = fb.playTimes.buyTimes.values().stream().mapToInt(a -> a).sum();
    if (!firstChallenge) {
      fb.playTimes.added();
    }
    int buyTimeAfter = fb.playTimes.buyTimes.values().stream().mapToInt(a -> a).sum();
    int dBuyTime = buyTimeAfter - buyTimeOrigin;
    MixRes consume = new MixRes();
    consume.addList(fb.playTimes.extraCost);
    consume.multiply(dBuyTime);

//        master.history.action.dailyFbChallenge(type, 1);
//        master.history.action.dailyFbChallenge(combatNum);
//        SA.stat.participate.record(master, GDDailyFb.Type.toFuncId(type));
    role.getHistory().action.dailyFB(1);
    role.getHistory().action.challengeDailyFb(type, 1);
    role.getTrace().challengeDailyFB(type, 1);
    r.data = fb;
    return r.success();
  }

  public void checkPosition() {
    if (role.getFight().funcPositions.get(GDFunc.DAILY_FB) == null
            || role.getFight().funcPositions.get(GDFunc.DAILY_FB).positions.isEmpty()) {
      Position position = role.getFight().getPosition(ADVENTURE);
      if (position != null) {
        FuncPosition funcPosition = new FuncPosition();
        funcPosition.init();
        funcPosition.funcId = GDFunc.DAILY_FB;
        funcPosition.positions.add(position.copy());
        role.getGame().fight.position.updatePosition(role, funcPosition);
      }
    }
  }

  private EcResult getTimes(DailyFb fb, int type, String costCode) {
    fb.playTimes.extraCost = new MixRes(costCode);
    return fb.playTimes.available(
            role, GDDailyFb.Type.toFuncId(type));
  }

  public EcResult<MixRes> batchMop(int type, boolean pay, DailyFb fb) {
    EcResult r = new EcResult();
    r.data = new MixRes();
    if (fb.combatNumPass == 0)
      return r.fail("当前副本不存在可扫荡关卡");
    DailyFbCombatRow tpl = role.getGame().table.dailyFb.combat.find(type, fb.combatNumPass);
    if (tpl == null) {
      return r.fail("模板表中找不到该关卡");
    }

    int mopTime = 0;
    int freeTimeRest = fb.playTimes.freeTimes.values().stream().mapToInt(a -> a).sum();
    while (true) {
      if (pay) {
        // 免费次数和付费次数都用
        EcResult available = getTimes(fb, type, tpl.challengeCostCode);

//                new MixRes(tpl.challengeCostCode)
//                , tpl.challengeCost
        if (!available.ok()) {
          break;
        }
        fb.playTimes.added();
        mopTime++;
      } else {
        // 只用免费次数
        EcResult freeAvaible =
                fb.playTimes.checkFree(role, GDDailyFb.Type.toFuncId(type));
        if (!freeAvaible.ok()) {
          break;
        }
        fb.playTimes.added();
        mopTime++;
      }
    }

    if (mopTime <= 0) {
      return r.fail("没有可用的扫荡次数");
    }
    MixRes reward;
    MixRes rewardSwap = new MixRes(tpl.rewardSwapCode);
    reward = rewardSwap.copy().multiply(mopTime);
    MixRes consume = new MixRes();
    consume.addList(fb.playTimes.extraCost);
    int buyTime = mopTime - freeTimeRest;
    consume.multiply(buyTime);

    role.getHistory().action.dailyFB(mopTime);
    role.getHistory().action.challengeDailyFb(type, mopTime);
    role.getTrace().challengeDailyFB(type, mopTime);
    role.getHistory().action.dailyFBWin(mopTime);
    r.data = reward;
    return r.success();
  }

  public GameResult<MixRes> allBatchMop(DailyFb fb, int times) {
    GameResult<MixRes> r = new GameResult<>();
    r.data = new MixRes();
    if (fb.combatNumPass == 0)
      return r.fail("当前副本不存在可扫荡关卡");
    DailyFbCombatRow tpl = role.getGame().table.dailyFb.combat.find(fb.type, fb.combatNumPass);
    if (tpl == null) {
      return r.fail("模板表中找不到该关卡");
    }
    int mopTimes = 0;
    for (int i = 0; i < times; ++ i) {
      EcResult available = getTimes(fb, fb.type, tpl.challengeCostCode);
      if (!available.ok()) {
        break;
      }
      fb.playTimes.added();
      mopTimes ++;
    }
    MixRes reward = new MixRes(tpl.rewardSwapCode).multiply(mopTimes);

    role.getHistory().action.dailyFB(mopTimes);
    role.getHistory().action.challengeDailyFb(fb.type, mopTimes);
    role.getTrace().challengeDailyFB(fb.type, mopTimes);
    role.getHistory().action.dailyFBWin(mopTimes);
    r.data = reward;
    return r.success();
  }

  public GameResult<Void> allBatchMopAll(List<MopType> types) {
    GameResult<Void> r = new GameResult<>();
    if (!isOpen()) {
      return r.fail("功能未开启");
    }
    if (CollectionUtils.isEmpty(types)) {
      return r.fail("请选择要扫荡的副本");
    }
    MixRes reward = new MixRes();
    for (MopType mopType : types) {
      DailyFbTypeRow row = role.getGame().table.dailyFb.type.get(mopType.type);
      if (row == null || mopType.times <= 0) {
        continue;
      }
      DailyFb fb = getFb(mopType.type);
      EcResult<MixRes> mopRes = allBatchMop(fb, mopType.times);
      if (mopRes.ok()) {
        reward.addList(mopRes.data);
      }
    }
    if (reward.isEmpty()) {
      return r.fail("您没有可以扫荡的副本噢");
    }
    reward.add(role, true, GDOperation.ALL_DAILY_FB_MOP_REWARD);
    role.getGame().notice.dialogReward(role, reward);
    return r.success();
  }

  public EcResult<DailyFb> batchMopType(int type, boolean pay) {
    EcResult r = new EcResult();
    if (!isOpen()) {
      return r.fail("功能未开启");
    }
    MixRes reward = new MixRes();
    DailyFb fb = getFb(type);
    if (fb.playTimes == null) {
      fb.initialize(role);
    }
    EcResult<MixRes> rFb = batchMop(type, pay, fb);
    reward.addList(rFb.data);

    reward.add(role, true, GDOperation.DAILY_FB_MOP_REWARD);
    role.getGame().notice.dialogReward(role, reward);
    return r.success();
  }


  public EcResult<Void> gmOpenLevel(int type, int combatNumOpen, int numPass) {
    EcResult r = new EcResult();
    if (!isOpen()) {
      return r.fail("功能未开启");
    }
    DailyFb fb = getFb(type);
    if (fb == null) {
      return r.fail("副本类型不存在");
    }
    if (fb.playTimes == null) {
      fb.initialize(role);
    }
    fb.combatNumOpen = combatNumOpen;
    fb.combatNumPass = numPass;
    role.sendNow(new DailyFbOneResp(fb));
    return r.success();
  }
}
